package snmp

import (
	"fmt"
	"pids-cloud-server/entity"
	"pids-cloud-server/logging"
	"time"

	"github.com/gosnmp/gosnmp"
)

// 创建SNMP客户端
func createSNMPClient(info *entity.SnmpInfo) *gosnmp.GoSNMP {
	return &gosnmp.GoSNMP{
		Target:    info.IP, // 替换为目标服务器的IP
		Port:      161,
		Version:   gosnmp.Version2c,
		Community: info.Community, // 替换为适当的社区字符串
		Timeout:   time.Duration(2) * time.Second,
		Retries:   1,
		MaxOids:   60,
	}
}
func InitSnmpDataAcquisition(info *entity.SnmpInfo) *SnmpDataAcquisition {
	snmpclient := createSNMPClient(info)
	return &SnmpDataAcquisition{
		Snmpclient: snmpclient,
	}
}

type SnmpDataAcquisition struct {
	Snmpclient *gosnmp.GoSNMP
}

// AcquireBaseInfo /*采集设备基础信息*/
func (s *SnmpDataAcquisition) AcquireBaseInfo(snmpOidMap map[string]entity.SnmpOid) (DeviceInfo, error) {
	var oidlist []string
	oidlist = append(oidlist, snmpOidMap[SysDescr].OidValue)
	oidlist = append(oidlist, snmpOidMap[SysObjectID].OidValue)
	g := s.Snmpclient
	result, err := g.Get(oidlist)
	if err != nil {
		logging.Error("SNMP  get BaseInfo error:", err)
		return DeviceInfo{}, fmt.Errorf("failed to get SNMP OIDs: %v", err)
	}
	var resultList []string
	variables := result.Variables
	for _, variable := range variables {
		switch variable.Type {
		case gosnmp.OctetString:
			resultList = append(resultList, string(variable.Value.([]byte)))
		case gosnmp.ObjectIdentifier:
			// ... or often you're just interested in numeric values.
			// ToBigInt() will return the Value as a BigInt, for plugging
			// into your calculations.
			resultList = append(resultList, variable.Value.(string))
		}
	}
	deviceName := resultList[0]
	manufacturer := manufacturerEstimate(resultList[1])
	return DeviceInfo{manufacturer, "", deviceName}, nil
}

// AcquireUptime /*采集运行时间*/
func (s *SnmpDataAcquisition) AcquireUptime(snmpOidMap map[string]entity.SnmpOid) (float64, error) {
	oidValue := snmpOidMap[SysTime].OidValue
	g := s.Snmpclient
	result, err := g.Get([]string{oidValue})
	if err != nil {
		logging.Error("SNMP get Uptime error:", err)
		return 0, fmt.Errorf("failed to get SNMP OIDs: %v", err)
	}
	uptime := result.Variables[0].Value.(uint32)
	floatuptime := float64(uptime) / 100
	return floatuptime, nil
}

// AcquireMemoryUsage /*采集内存使用情况*/
func (s *SnmpDataAcquisition) AcquireMemoryUsage(snmpOidMap map[string]entity.SnmpOid) (MemoryInfo, error) {
	return MemoryInfo{}, nil
}

// AcquireCpu /*采集CPU信息*/
func (s *SnmpDataAcquisition) AcquireCpu(snmpOidMap map[string]entity.SnmpOid) (float64, error) {
	return 0, nil
}

// AcquireDisk /*采集磁盘使用情况*/
func (s *SnmpDataAcquisition) AcquireDisk(snmpOidMap map[string]entity.SnmpOid) (StorageDto, error) {
	return StorageDto{}, nil
}

// CheckSnmpAvailable /* 检查SNMP服务是否可用*/
func (s *SnmpDataAcquisition) CheckSnmpAvailable(snmpOidMap map[string]entity.SnmpOid) bool {
	// 用主client的信息新建一个临时client
	g := s.Snmpclient
	err := g.Connect()
	if err != nil {
		logging.Error("SNMP Connect失败：", err)
		return false
	}
	oid := snmpOidMap[SysDescr].OidValue
	result, err := g.Get([]string{oid})
	if err != nil {
		logging.Error("SNMP Get sysDescr.0失败,SNMP服务不可用，原因：", err)
		return false
	}
	if result == nil || len(result.Variables) == 0 {
		return false
	}
	return true
}
